import asyncio
import hashlib
import re
import time
from urllib.parse import urlencode

import aiohttp
import async_lru
from cachetools import TTLCache

from app_v2.bili_api.common import mixin_key, headers_, headers_with_cookie
from app_v2.bili_api.model import VideoInfo


class Bvid:
    _video_cache = TTLCache(maxsize=100, ttl=300)
    _ai_desc_cache = TTLCache(maxsize=100, ttl=300)
    _video_info_cache = TTLCache(maxsize=10, ttl=60)
    _bvid_regex = re.compile(r'(?:https://)?(?:www\.)?bilibili\.com/video/(\w+).*')

    def __init__(self, bvid: str, session):
        self.bvid = bvid
        self.session = session

    @async_lru.alru_cache(maxsize=40, ttl=300)
    async def info(self):
        detail_url = f"https://api.bilibili.com/x/web-interface/view/detail?bvid={self.bvid}"
        ret = await self.session.fetch_data(detail_url)
        return VideoInfo(data["View"], data["Tags"]) if (
            data := ret.get("data")) else None

    # summary,  #data -> model_result -> summary
    @async_lru.alru_cache(maxsize=40, ttl=300)
    async def ai_desc(self):
        url = """https://api.bilibili.com/x/web-interface/view/conclusion/get"""
        info = await self.info()
        params = {
            "bvid": self.bvid,
            "cid": info.cid,
            "up_mid": info.mid,
            "wts": str(int(time.time()))
        }
        code = urlencode(params)
        code += mixin_key
        w_rid = hashlib.md5(code.encode()).hexdigest()
        params["w_rid"] = w_rid
        return await self.session.fetch_data(url, params=params)

    @staticmethod
    @async_lru.alru_cache(maxsize=40, ttl=300)
    async def get_rank_video(tid=0):
        url = f"https://api.bilibili.com/x/web-interface/ranking/v2?rid={tid}"
        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers_) as resp:
                resp = await resp.json()
        return list(map(lambda item: VideoInfo(item, []), resp["data"]["list"]))

    async def reply_info(self):
        url = f"https://api.bilibili.com/x/v2/reply?type=1&oid={self.bvid}"
        resp = self.session.fetch_data(url, headers=headers_)
        return list(map(lambda item: item["content"]["message"], resp["data"]["replies"]))

    @staticmethod
    async def video_recommended():
        url = "https://app.bilibili.com/x/v2/feed/index/story"
        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers_) as resp:
                res = await resp.json()
        return [{
            "bvid": item["bvid"],
            "pic": item["cover"],
            "desc": desc if (desc := item.get("desc")) else "",
            "view": item["stat"]["view"],
            "pubdate": item.get("pubdate"),
            "title": item["title"],
        } for item in res["data"]["items"]]

    @staticmethod
    async def popular(ps=20, pn=1, cookie: str = None):
        url = "https://api.bilibili.com/x/web-interface/popular"
        async with aiohttp.ClientSession(headers=headers_with_cookie(cookie if cookie else "")) as session:
            data = await session.get(url, params={"ps": ps, "pn": pn})
            data = await data.json()
        return [VideoInfo(item, []).to_dict() for item in data["data"]["list"]]

    @staticmethod
    async def lastest_series(cookie: str = None):
        cookie = cookie if cookie else """buvid3=BD59CD6B-AAC9-9F3E-2376-22589926A56F41075infoc; b_nut=1751854541; _uuid=10A3D6B4F-D52B-91C9-7C510-A3F5571012C3B40933infoc; buvid_fp=c41e9eb010dd2c33e9bb1a59e8953ce1; header_theme_version=OPEN; enable_web_push=DISABLE; home_feed_column=4; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NTIxMTM3NDIsImlhdCI6MTc1MTg1NDQ4MiwicGx0IjotMX0.sX9904NaoEty1RFEBFZZPkb_0OI2bdH3rybrzpmBKwI; bili_ticket_expires=1752113682; buvid4=8AF54D69-2D8A-B5DD-058F-975C15E2E6A642416-025070710-LfJT64UxyVOHMN4QKb5hBQ%3D%3D; browser_resolution=1003-487; CURRENT_FNVAL=2000; sid=h0z90oc7; b_lsid=E17E383E_197E2FD6C1E"""
        list_url = "https://api.bilibili.com/x/web-interface/popular/series/list"
        video_url = "https://api.bilibili.com/x/web-interface/popular/series/one"
        async with aiohttp.ClientSession(headers=headers_with_cookie(cookie)) as session:
            async with session.get(list_url) as resp:
                data = await resp.json()
            num = data['data']["list"][0]["number"]
            async with session.get(video_url, params={"number": num}) as resp:
                data = await resp.json()
        return [VideoInfo(info, []).to_dict() for info in data["data"]["list"]]


if __name__ == '__main__':
    data = asyncio.run(Bvid.lastest_series(cookie=None))
    print(data)
